package com.dylan.channel.v11.handler;

import com.dylan.channel.v11.attribute.Attribute;
import com.dylan.channel.v11.attribute.AttributeKey;
import com.dylan.channel.v11.channel.Channel;
import com.dylan.channel.v11.future.ChannelFuture;
import com.dylan.channel.v11.future.ChannelPromise;

import java.net.SocketAddress;

public abstract class AbstractChannelHandlerContext implements ChannelHandlerContext {
    /**
     * @Author: PP-jessica
     * @Description:这是个很有意思的属性，变量名称为执行掩码，看名字肯定一头雾水，用起来却很有意思。 试想一下，也许我们会向ChannelPipeline中添加很多handler，每个handler都有很多方法，如果有的handler并不对某个事件感兴趣，
     * 处理事件的时候，就会自动跳过该handler。这个掩码，就是表明该handler对哪个事件感兴趣的
     */
    private final int executionMask;

    /**
     * @Author: PP-jessica
     * @Description:链表的前一个节点和后一个节点
     */
    volatile AbstractChannelHandlerContext next;
    volatile AbstractChannelHandlerContext prev;

    /**
     * @Author: PP-jessica
     * @Description:ChannelPipeline可以得到每一个ChannelHandler，而每一个封装着ChannelHandler的ChannelHandlerContext又可以得到 自己所在的链表
     */
    private final DefaultChannelPipeline pipeline;

    //构造方法
    public AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, Class<? extends ChannelHandler> handlerClass) {
        this.executionMask = ChannelHandlerMask.mask(handlerClass);
        this.pipeline = pipeline;
    }

    @Override
    public <T> Attribute<T> attr(AttributeKey<T> key) {
        return null;
    }

    @Override
    public <T> boolean hasAttr(AttributeKey<T> key) {
        return false;
    }

    @Override
    public ChannelHandler handler() {
        return null;
    }

    @Override
    public ChannelHandlerContext read() {
        return null;
    }

    @Override
    public ChannelHandlerContext flush() {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireChannelRegistered() {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireChannelUnregistered() {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireChannelActive() {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireChannelInactive() {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireExceptionCaught(Throwable cause) {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireUserEventTriggered(Object event) {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireChannelReadComplete() {
        return null;
    }

    @Override
    public ChannelInboundInvoker fireChannelWritabilityChanged() {
        return null;
    }

    @Override
    public ChannelFuture bind(SocketAddress localAddress) {
        return null;
    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress) {
        return null;
    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
        return null;
    }

    @Override
    public ChannelFuture disconnect() {
        return null;
    }

    @Override
    public ChannelFuture close() {
        return null;
    }

    @Override
    public ChannelFuture deregister() {
        return null;
    }

    @Override
    public ChannelFuture bind(final SocketAddress localAddress, ChannelPromise promise) {
        next.invokeBind(localAddress, promise);
        return promise;
    }

    private void invokeBind(SocketAddress localAddress, ChannelPromise promise) {

    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture close(ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture write(Object msg) {
        return null;
    }

    @Override
    public ChannelFuture write(Object msg, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture writeAndFlush(Object msg) {
        return null;
    }

    @Override
    public ChannelPromise newPromise() {
        return null;
    }


    static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
        //在这里，调用该类中私有的invokeChannelRead方法
        //也就是下面的那个方法
        next.invokeChannelRead(msg);
    }

    private void invokeWriteAndFlush(Object msg) {
        // ((ChannelOutboundHandler) handler()).write(this, msg);
    }

    private void invokeChannelRead(Object msg) {
        //handler方法，可以得到AbstractChannelHandlerContext包装的消息处理器
        //对象ChannelHandler，然后调用这个处理器的channelRead方法即可
        try {
            ((ChannelInboundHandler) handler()).channelRead(this, msg);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //将消息向链表下一个节点传递的方法
    public AbstractChannelHandlerContext fireChannelRead(final Object msg) {

        //在这里得到链表的下一个节点
        AbstractChannelHandlerContext ctx = this;
        do {
            //因为是消息入站，所以要向前后找节点
            ctx = ctx.next;
            //如果找到的是出站处理器，就跳过它，继续向后寻找入站处理器
        } while (ctx.handler() instanceof ChannelOutboundHandler);
        //调用下一个节点的ChannelRead方法
        try {
            invokeChannelRead(ctx, msg);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return this;
    }

    @Override
    public Channel channel() {
        return pipeline.channel();
    }

    @Override
    public ChannelPipeline pipeline() {
        return pipeline;
    }
}
